"""
全局异常处理模块
"""

from fastapi import Request, HTTPException
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException
from typing import Union, Dict, Any
import logging
import traceback
from datetime import datetime

from .logging import error_logger


class BaseException(Exception):
    """基础异常类"""
    
    def __init__(
        self,
        message: str,
        code: str = None,
        details: Dict[str, Any] = None
    ):
        self.message = message
        self.code = code or self.__class__.__name__
        self.details = details or {}
        super().__init__(self.message)


class ValidationError(BaseException):
    """验证错误"""
    pass


class NotFoundError(BaseException):
    """资源未找到错误"""
    pass


class AuthenticationError(BaseException):
    """认证错误"""
    pass


class AuthorizationError(BaseException):
    """授权错误"""
    pass


class BusinessLogicError(BaseException):
    """业务逻辑错误"""
    pass


class ExternalServiceError(BaseException):
    """外部服务错误"""
    pass


class DatabaseError(BaseException):
    """数据库错误"""
    pass


class FileOperationError(BaseException):
    """文件操作错误"""
    pass


class TTSSError(BaseException):
    """TTS服务错误"""
    pass


class VideoProcessingError(BaseException):
    """视频处理错误"""
    pass


class AudioProcessingError(BaseException):
    """音频处理错误"""
    pass


class CacheError(BaseException):
    """缓存操作错误"""
    pass


class RateLimitError(BaseException):
    """速率限制错误"""
    pass


class ConfigurationError(BaseException):
    """配置错误"""
    pass


async def base_exception_handler(request: Request, exc: BaseException) -> JSONResponse:
    """基础异常处理器"""
    error_id = f"error_{datetime.utcnow().timestamp()}"
    
    # 记录错误
    error_logger.log_exception(
        exc,
        context={
            "error_id": error_id,
            "path": str(request.url),
            "method": request.method,
            "client_ip": request.client.host,
            "user_agent": request.headers.get("user-agent")
        }
    )
    
    # 构建错误响应
    response_data = {
        "success": False,
        "error": {
            "code": exc.code,
            "message": exc.message,
            "details": exc.details,
            "error_id": error_id,
            "timestamp": datetime.utcnow().isoformat()
        }
    }
    
    # 根据异常类型设置状态码
    status_code_map = {
        ValidationError: 400,
        AuthenticationError: 401,
        AuthorizationError: 403,
        NotFoundError: 404,
        RateLimitError: 429,
        ExternalServiceError: 502,
        DatabaseError: 500,
        FileOperationError: 500,
        TTSSError: 500,
        VideoProcessingError: 500,
        AudioProcessingError: 500,
        BusinessLogicError: 400,
        ConfigurationError: 500
    }
    
    status_code = status_code_map.get(type(exc), 500)
    
    return JSONResponse(
        status_code=status_code,
        content=response_data
    )


async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
    """HTTP异常处理器"""
    error_id = f"error_{datetime.utcnow().timestamp()}"
    
    # 记录错误
    error_logger.log_error(
        f"HTTP Exception: {exc.status_code} - {exc.detail}",
        context={
            "error_id": error_id,
            "path": str(request.url),
            "method": request.method,
            "status_code": exc.status_code,
            "detail": exc.detail,
            "headers": dict(exc.headers) if exc.headers else None
        }
    )
    
    response_data = {
        "success": False,
        "error": {
            "code": "HTTP_EXCEPTION",
            "message": exc.detail,
            "status_code": exc.status_code,
            "error_id": error_id,
            "timestamp": datetime.utcnow().isoformat()
        }
    }
    
    return JSONResponse(
        status_code=exc.status_code,
        content=response_data
    )


async def validation_exception_handler(request: Request, exc: RequestValidationError) -> JSONResponse:
    """请求验证异常处理器"""
    error_id = f"error_{datetime.utcnow().timestamp()}"
    
    # 格式化验证错误
    validation_errors = []
    for error in exc.errors():
        validation_errors.append({
            "field": ".".join(str(x) for x in error["loc"]),
            "message": error["msg"],
            "type": error["type"]
        })
    
    # 记录错误
    error_logger.log_error(
        f"Validation Exception: {len(validation_errors)} validation errors",
        context={
            "error_id": error_id,
            "path": str(request.url),
            "method": request.method,
            "validation_errors": validation_errors
        }
    )
    
    response_data = {
        "success": False,
        "error": {
            "code": "VALIDATION_ERROR",
            "message": "Request validation failed",
            "validation_errors": validation_errors,
            "error_id": error_id,
            "timestamp": datetime.utcnow().isoformat()
        }
    }
    
    return JSONResponse(
        status_code=422,
        content=response_data
    )


async def general_exception_handler(request: Request, exc: Exception) -> JSONResponse:
    """通用异常处理器"""
    error_id = f"error_{datetime.utcnow().timestamp()}"
    
    # 记录错误
    error_logger.log_exception(
        exc,
        context={
            "error_id": error_id,
            "path": str(request.url),
            "method": request.method,
            "client_ip": request.client.host,
            "user_agent": request.headers.get("user-agent"),
            "traceback": traceback.format_exc()
        }
    )
    
    # 在生产环境中不暴露详细的错误信息
    from .config import settings
    
    if settings.is_production:
        message = "An internal server error occurred"
        details = {}
    else:
        message = str(exc)
        details = {
            "exception_type": type(exc).__name__,
            "traceback": traceback.format_exc()
        }
    
    response_data = {
        "success": False,
        "error": {
            "code": "INTERNAL_SERVER_ERROR",
            "message": message,
            "details": details,
            "error_id": error_id,
            "timestamp": datetime.utcnow().isoformat()
        }
    }
    
    return JSONResponse(
        status_code=500,
        content=response_data
    )


def setup_exception_handlers(app):
    """设置异常处理器"""
    # 基础异常
    app.add_exception_handler(BaseException, base_exception_handler)
    
    # HTTP异常
    app.add_exception_handler(HTTPException, http_exception_handler)
    app.add_exception_handler(StarletteHTTPException, http_exception_handler)
    
    # 验证异常
    app.add_exception_handler(RequestValidationError, validation_exception_handler)
    
    # 通用异常
    app.add_exception_handler(Exception, general_exception_handler)


class ErrorReporter:
    """错误报告器"""
    
    def __init__(self):
        self.logger = logging.getLogger("error_reporter")
    
    def report_error(self, error: Exception, context: Dict[str, Any] = None):
        """报告错误"""
        error_info = {
            "type": type(error).__name__,
            "message": str(error),
            "context": context or {},
            "timestamp": datetime.utcnow().isoformat()
        }
        
        self.logger.error(f"Error reported: {error_info}")
        
        # 这里可以添加外部错误报告服务，如Sentry
        # try:
        #     import sentry_sdk
        #     sentry_sdk.capture_exception(error)
        # except ImportError:
        #     pass
    
    def report_critical_error(self, error: Exception, context: Dict[str, Any] = None):
        """报告严重错误"""
        error_info = {
            "type": type(error).__name__,
            "message": str(error),
            "context": context or {},
            "timestamp": datetime.utcnow().isoformat(),
            "severity": "critical"
        }
        
        self.logger.critical(f"Critical error reported: {error_info}")
        
        # 严重错误需要立即通知
        self._send_alert(error_info)
    
    def _send_alert(self, error_info: Dict[str, Any]):
        """发送告警"""
        # 这里可以实现邮件、短信、Slack等告警机制
        pass


# 创建全局错误报告器
error_reporter = ErrorReporter()


def safe_execute(func, *args, default=None, **kwargs):
    """安全执行函数"""
    try:
        return func(*args, **kwargs)
    except Exception as e:
        error_reporter.report_error(e, context={"function": func.__name__})
        return default


async def safe_execute_async(func, *args, default=None, **kwargs):
    """安全执行异步函数"""
    try:
        return await func(*args, **kwargs)
    except Exception as e:
        error_reporter.report_error(e, context={"function": func.__name__})
        return default


class ErrorContext:
    """错误上下文管理器"""
    
    def __init__(self, operation: str, context: Dict[str, Any] = None):
        self.operation = operation
        self.context = context or {}
        self.start_time = None
    
    def __enter__(self):
        self.start_time = datetime.utcnow()
        self.logger = logging.getLogger(f"operation.{self.operation}")
        self.logger.info(f"Starting operation: {self.operation}")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        duration = (datetime.utcnow() - self.start_time).total_seconds()
        
        if exc_type is None:
            self.logger.info(f"Operation completed: {self.operation} in {duration:.3f}s")
        else:
            error_logger.log_exception(
                exc_val,
                context={
                    "operation": self.operation,
                    "duration": duration,
                    **self.context
                }
            )
        
        return False  # 不抑制异常


def with_error_handling(operation: str, context: Dict[str, Any] = None):
    """错误处理装饰器"""
    import asyncio
    from functools import wraps
    
    def decorator(func):
        if asyncio.iscoroutinefunction(func):
            @wraps(func)
            async def async_wrapper(*args, **kwargs):
                with ErrorContext(operation, context):
                    return await func(*args, **kwargs)
            return async_wrapper
        else:
            @wraps(func)
            def sync_wrapper(*args, **kwargs):
                with ErrorContext(operation, context):
                    return func(*args, **kwargs)
            return sync_wrapper
    
    return decorator
